#include "Die.h"

#include <cstdio>
#include <cstring>

#include <libdwarf/dwarf.h>

namespace dwarf {

RaiiDie Die::getChild(Dwarf_Debug _debug, Dwarf_Die _die) {
	Dwarf_Error error;
	RaiiDie die(_debug);
	int rtn = dwarf_child(_die, &die.getPointer(), &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return die;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return die;
	}
	return die;
}

RaiiDie Die::getSibling(Dwarf_Debug _debug, Dwarf_Die _die) {
	Dwarf_Error error;
	RaiiDie die(_debug);
	int rtn = dwarf_siblingof(_debug, _die, &die.getPointer(), &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return die;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return die;
	}
	return die;
}

int Die::getTag(Dwarf_Die _die, Dwarf_Half &_tag) {
	Dwarf_Error error;
	return dwarf_tag(_die, &_tag, &error);
}

int Die::getAttribute(Dwarf_Die _die, Dwarf_Half _type, RaiiPointer<Dwarf_Attribute> &_attribute) {
	Dwarf_Error error;
	return dwarf_attr(_die, _type, &_attribute.getPointer(), &error);
}

int Die::getAbstractOrigin(Dwarf_Attribute _attribute, Dwarf_Off &_abstractOrigin) {
	Dwarf_Error error;
	return dwarf_formref(_attribute, &_abstractOrigin, &error);
}

int Die::getAbstractOrigin(Dwarf_Debug _debug, Dwarf_Die _die, Dwarf_Off &_abstractOrigin) {
	dwarf::RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = dwarf::Die::getAttribute(_die, DW_AT_abstract_origin, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	rtn = getAbstractOrigin(attribute.getPointer(), _abstractOrigin);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	return rtn;
}

int Die::getBitOffset(Dwarf_Debug _debug, Dwarf_Die _die, Dwarf_Unsigned &_bitOffset) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_bit_offset, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	Dwarf_Error error;
	return dwarf_formudata(attribute.getPointer(), &_bitOffset, &error);
}

int Die::getBitSize(Dwarf_Attribute _attribute, Dwarf_Unsigned &_bitSize) {
	Dwarf_Error error;
	return dwarf_formudata(_attribute, &_bitSize, &error);
}

int Die::getConstValue(Dwarf_Debug _debug, Dwarf_Attribute _attribute, Value &_constValue) {
	Dwarf_Error error;
	Dwarf_Half attributeFormat;
	int rtn = dwarf_whatform(_attribute, &attributeFormat, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	switch (attributeFormat) {
		case DW_FORM_block1:
		case DW_FORM_block2:
		case DW_FORM_block4: {
			RaiiPointer<Dwarf_Block *> block(_debug);
			rtn = dwarf_formblock(_attribute, &block.getPointer(), &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			if (block.getPointer()->bl_len > sizeof(_constValue.getData())) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			memcpy(_constValue.getData().block_, block.getPointer()->bl_data, block.getPointer()->bl_len);
			_constValue.setFormat(attributeFormat);
			return rtn;
		}
		case DW_FORM_data1:
		case DW_FORM_data2:
		case DW_FORM_data4:
		case DW_FORM_data8:
		case DW_FORM_sdata: {
			rtn = dwarf_formsdata(_attribute, &_constValue.getData().sLarge_, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			_constValue.setFormat(attributeFormat);
			return rtn;
		}
		case DW_FORM_udata: {
			rtn = dwarf_formudata(_attribute, &_constValue.getData().uLarge_, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			_constValue.setFormat(attributeFormat);
			return rtn;
		}
		default: {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return DW_DLV_ERROR;
		}
	}
}

int Die::getConstValue(Dwarf_Debug _debug, Dwarf_Die _die, Value &_constValue) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_const_value, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	rtn = getConstValue(_debug, attribute.getPointer(), _constValue);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	return rtn;
}

int Die::getEncoding(Dwarf_Debug _debug, Dwarf_Die _die, Dwarf_Unsigned &_encoding) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_encoding, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	Dwarf_Error error;
	rtn = dwarf_formudata(attribute.getPointer(), &_encoding, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_OK) {
		return rtn;
	}
	Dwarf_Signed s;
	rtn = dwarf_formsdata(attribute.getPointer(), &s, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_OK) {
		_encoding = (Dwarf_Unsigned) s;
		return rtn;
	}
	Dwarf_Off offset;
	rtn = dwarf_global_formref(attribute.getPointer(), &offset, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_OK) {
		_encoding = offset;
		return rtn;
	}
	fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
	return DW_DLV_ERROR;
}

int Die::getExternal(Dwarf_Attribute _attribute, bool &_external) {
	Dwarf_Error error;
	Dwarf_Half attributeFormat;
	int rtn = dwarf_whatform(_attribute, &attributeFormat, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	_external = attributeFormat == DW_FORM_flag_present;
	return rtn;
}

int Die::getHighPc(Dwarf_Debug _debug, Dwarf_Die _die, const void *_lowPc, void *&_highPc) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_high_pc, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	Dwarf_Error error;
	Dwarf_Half attributeFormat;
	rtn = dwarf_whatform(attribute.getPointer(), &attributeFormat, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	switch (attributeFormat) {
		case DW_FORM_addr: {
			Dwarf_Addr address;
			rtn = dwarf_formaddr(attribute.getPointer(), &address, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			_highPc = (void *) address;
			return rtn;
		}
		case DW_FORM_data8: {
			Dwarf_Unsigned offset;
			rtn = dwarf_formudata(attribute.getPointer(), &offset, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			_highPc = (char *) _lowPc + offset;
			return rtn;
		}
		default: {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return DW_DLV_ERROR;
		}
	}
}

int Die::getLocationDescription(Dwarf_Debug _debug, Dwarf_Die _die, Dwarf_Attribute _attribute, RaiiPointer<Dwarf_Locdesc *> &_locationDescription) {
	Dwarf_Error error;
	Dwarf_Half attributeFormat;
	int rtn = dwarf_whatform(_attribute, &attributeFormat, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	switch (attributeFormat) {
		case DW_FORM_block1:
		case DW_FORM_block2:
		case DW_FORM_block4:
		case DW_FORM_block:
		case DW_FORM_data4:
		case DW_FORM_data8:
		case DW_FORM_sec_offset: {
			Dwarf_Signed locationCount;
			rtn = dwarf_loclist(_attribute, &_locationDescription.getPointer(), &locationCount, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				return rtn;
			}
			return rtn;
		}
		case DW_FORM_exprloc: {
			Dwarf_Unsigned expressionLength;
			Dwarf_Ptr expression;
			rtn = dwarf_formexprloc(_attribute, &expressionLength, &expression, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			Dwarf_Half addressSize;
			rtn = dwarf_get_die_address_size(_die, &addressSize, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return DW_DLV_ERROR;
			}
			Dwarf_Half version = 0;
			Dwarf_Half offsetSize = 0;
			rtn = dwarf_get_version_of_die(_die, &version, &offsetSize);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				return rtn;
			}
			Dwarf_Signed locationCount;
			rtn = dwarf_loclist_from_expr_b(_debug, expression, expressionLength, addressSize, offsetSize, (Dwarf_Small) version, &_locationDescription.getPointer(), &locationCount, &error);
			if (rtn == DW_DLV_ERROR) {
				fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
				return rtn;
			}
			else if (rtn == DW_DLV_NO_ENTRY) {
				return rtn;
			}
			return rtn;
		}
		default: {
			fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
			return DW_DLV_ERROR;
		}
	}
}

int Die::getLocationDescription(Dwarf_Debug _debug, Dwarf_Die _die, RaiiPointer<Dwarf_Locdesc *> &_locationDescription) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_location, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	rtn = getLocationDescription(_debug, _die, attribute.getPointer(), _locationDescription);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	return rtn;
}

int Die::getName(Dwarf_Die _die, RaiiPointer<char *> &_name) {
	Dwarf_Error error;
	return dwarf_diename(_die, &_name.getPointer(), &error);
}

int Die::getType(Dwarf_Debug _debug, Dwarf_Die _die, RaiiPointer<Dwarf_Die> &_type) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_type, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	Dwarf_Error error;
	Dwarf_Off offset;
	rtn = dwarf_formref(attribute.getPointer(), &offset, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	return dwarf_offdie(_debug, offset, &_type.getPointer(), &error);
}

int Die::getUpperBound(Dwarf_Debug _debug, Dwarf_Die _die, Dwarf_Unsigned &_upperBound) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_die, DW_AT_upper_bound, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	Dwarf_Error error;
	return dwarf_formudata(attribute.getPointer(), &_upperBound, &error);
}

bool Die::getArgumentAddress(Dwarf_Debug _debug, Dwarf_Die _argument, const void *_frame, void *&_address) {
	RaiiPointer<Dwarf_Locdesc *> locationDescription(_debug);
	int rtn = getLocationDescription(_debug, _argument, locationDescription);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return false;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return false;
	}
	for (Dwarf_Half i = 0; i < locationDescription.getPointer()->ld_cents; ++i) {
		switch (locationDescription.getPointer()->ld_s[i].lr_atom) {
			case DW_OP_addr: {
				_address = (void *) locationDescription.getPointer()->ld_s[i].lr_number;
				return true;
			}
			case DW_OP_fbreg: {
				_address = (void *) ((char *) _frame + locationDescription.getPointer()->ld_s[i].lr_number);
				return true;
			}
			default: {
				continue;
			}
		}
	}
	fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
	return false;
}

int Die::getLocalAddress(Dwarf_Debug _debug, Dwarf_Die _local, const void *_frame, void *&_address) {
	RaiiPointer<Dwarf_Locdesc *> locationDescription(_debug);
	int rtn = getLocationDescription(_debug, _local, locationDescription);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	if (locationDescription.getPointer()->ld_cents != 1) {
		return DW_DLV_NO_ENTRY;
	}
	switch (locationDescription.getPointer()->ld_s[0].lr_atom) {
		case DW_OP_addr: {
			_address = (void *) locationDescription.getPointer()->ld_s[0].lr_number;
			return DW_DLV_OK;
		}
		case DW_OP_fbreg: {
			_address = (void *) ((char *) _frame + locationDescription.getPointer()->ld_s[0].lr_number);
			return DW_DLV_OK;
		}
		default: {
			return DW_DLV_NO_ENTRY;
		}
	}
}

int Die::getMemberAddress(Dwarf_Debug _debug, Dwarf_Die _member, const void *_object, void *&_address) {
	RaiiPointer<Dwarf_Attribute> attribute(_debug);
	int rtn = getAttribute(_member, DW_AT_data_member_location, attribute);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	Dwarf_Half version = 0;
	Dwarf_Half offsetSize = 0;
	rtn = dwarf_get_version_of_die(_member, &version, &offsetSize);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	Dwarf_Error error;
	Dwarf_Half attributeFormat;
	rtn = dwarf_whatform(attribute.getPointer(), &attributeFormat, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_NO_ENTRY) {
		return rtn;
	}
	if (dwarf_get_form_class(version, DW_AT_data_member_location, offsetSize, attributeFormat) != DW_FORM_CLASS_CONSTANT) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return DW_DLV_ERROR;
	}
	Dwarf_Unsigned u;
	rtn = dwarf_formudata(attribute.getPointer(), &u, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_OK) {
		_address = (char *) _object + u;
		return rtn;
	}
	Dwarf_Signed s;
	rtn = dwarf_formsdata(attribute.getPointer(), &s, &error);
	if (rtn == DW_DLV_ERROR) {
		fprintf(stderr, "[ERR] (%s, %d) %s\n", __FILE__, __LINE__, __FUNCTION__);
		return rtn;
	}
	else if (rtn == DW_DLV_OK) {
		_address = (char *) _object + s;
		return rtn;
	}
	return DW_DLV_NO_ENTRY;
}

Die::Die() {
}

Die::~Die() {
}

}
